package com.fowo.api.common.model;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fowo.api.common.util.ListUtils;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.ReflectionUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Path;

/**
 * 提供导入行的详情信息
 * @author yl_ls
 */
@Getter
@Setter
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ImportRow<TRow> {

    /**
     * 原导入行号,
     */
    private Integer rowNumber;

    /**
     * 对于子表，保存父级行号
     */
    private Integer parentRowNumber;

    /** 是否为空行 */
    private boolean emptyRow;

    /** 导入行数据 */
    private TRow row;

    /** 要更新的数据编号 */
    private Long updateId;

    /** 错误列表 */
    private List<ImportFieldError> errors;

    /**
     * 获取所有错误的连接消息
     */
    public String getJoinErrorMessage() {
        if (errors == null) {
            return null;
        }
        return errors.stream().flatMap(es -> es.getErrorMessages().stream()).collect(Collectors.joining("；"));
    }

    /**
     * 使用校验结果集初始化错误信息
     * @param validate 校验结果集
     * @param rowClass 导入行类型
     */
    public void initErrors(Set<ConstraintViolation<TRow>> validate, Class<TRow> rowClass) {
        errors = new ArrayList<>();
        for(ConstraintViolation<TRow> cv : validate) {
            String field = solveFieldNameByPath(cv.getPropertyPath(), rowClass);
            if (field != null) {
                addError(field, cv.getMessage());
            } else {
                addError("", cv.getMessage());
            }
        }
    }

    private String solveFieldNameByPath(Path propertyPath, Class<TRow> rowClass) {
        final Field field = ReflectionUtils.findField(rowClass, propertyPath.toString());
        if (field != null) {
            return field.getName();
        }
        return null;
    }

    /**
     * 添加一个字段错误消息
     * @param field 字段名
     * @param errorMessage 错误信息
     */
    public void addError(String field, String errorMessage) {
        if (errors == null) {
            errors = new ArrayList<>();
        }
        ImportFieldError fieldError = ListUtils.find(errors, e -> e.field.equals(field));
        if (fieldError == null) {
            fieldError = new ImportFieldError();
            fieldError.setField(field);
            fieldError.setErrorMessages(new ArrayList<>());
            errors.add(fieldError);
        }
        fieldError.errorMessages.add(errorMessage);
    }

    @Getter
    @Setter
    public static class ImportFieldError {

        /** 发生错误的列名，不能为 null 但可以是空字符用于表示非特定字段的问题 */
        private String field;

        /** 错误消息列表 */
        private List<String> errorMessages;
    }
}